﻿using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Aribaccio;
using Aribaccio.Device;
using BDPAutodetect.Device;

namespace BDPAutodetect.Hardware
{
    public class DeviceParaManager
    {
        /// <summary>
        /// 名称
        /// </summary>
        protected string Name { get; set; }
        /// <summary>
        /// 设备管理
        /// </summary>
        protected DeviceManager Manager { get; set; }
        /// <summary>
        /// 设备配置列表集合
        /// </summary>
        public List<IDevicePara> DeviceParas { get; private set; }
        /// <summary>
        /// 设备配置集合数量
        /// </summary>
        public int Count { get { return this.DeviceParas != null ? this.DeviceParas.Count : 0; } }

        /// <summary>
        /// 构造函数
        /// </summary>
        public DeviceParaManager(DeviceManager deviceManager)
        {
            this.Name = "设备参数管理";
            this.Manager = deviceManager;
            this.DeviceParas = new List<IDevicePara>();
        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <returns></returns>
        public Result Initialize(ReturnData argReturnData)
        {
            Result ResultData = new Result();
            if (this.DeviceParas != null && this.DeviceParas.Count > 0) return ResultData;
            if (argReturnData == null)
            {
                ResultData.ResultCode = ResultStatus.Failure;
                ResultData.ResultMsg = $"{this.Name}-> 初始化失败：参数配置为空";
                return ResultData;
            }
            try
            {
                this.ClearDeviceAll();
                if (this.DeviceParas == null) { this.DeviceParas = new List<IDevicePara>(); }
                //存储设备数据对象
                foreach (ReturnDataRow item in argReturnData.DataRow)
                {
                    DeviceType deviceType = item.DataType.ToEnum<DeviceType>();
                    DeviceConnectType connectType = item.DataConnect.ToEnum<DeviceConnectType>();
                    if (connectType == DeviceConnectType.None || deviceType == DeviceType.None) continue;

                    ReturnDataItem? DataItem = null;
                    switch (connectType)
                    {
                        case DeviceConnectType.SerialPort:
                            IDeviceParaSerial deviceParaSerial = new DeviceParaSerial(item.DataKey, item.DataCaption, item.DataType);
                            DataItem = item.DataItem.Where(v => v.FieldName == "ModuleType").FirstOrDefault();
                            if (DataItem != null) deviceParaSerial.ModuleType = DataItem.FieldValue.ToEnum<DeviceModule>();
                            DataItem = item.DataItem.Where(v => v.FieldName == "PortName").FirstOrDefault();
                            if (DataItem != null) deviceParaSerial.PortName = DataItem.FieldValue;
                            DataItem = item.DataItem.Where(v => v.FieldName == "BaudRate").FirstOrDefault();
                            if (DataItem != null) deviceParaSerial.BaudRate = Convert.ToInt32(DataItem.FieldValue);
                            DataItem = item.DataItem.Where(v => v.FieldName == "DataBits").FirstOrDefault();
                            if (DataItem != null) deviceParaSerial.DataBits = Convert.ToInt32(DataItem.FieldValue);
                            DataItem = item.DataItem.Where(v => v.FieldName == "StopBits").FirstOrDefault();
                            if (DataItem != null) deviceParaSerial.StopBits = DataItem.FieldValue.ToEnum<StopBits>();
                            DataItem = item.DataItem.Where(v => v.FieldName == "ParityBits").FirstOrDefault();
                            if (DataItem != null) deviceParaSerial.ParityBits = DataItem.FieldValue.ToEnum<Parity>();
                            DataItem = item.DataItem.Where(v => v.FieldName == "AutoMode").FirstOrDefault();
                            if (DataItem != null) deviceParaSerial.AutoMode = Convert.ToBoolean(DataItem.FieldValue);
                            //新增设备配置
                            InsertDevicePara(deviceParaSerial);
                            break;
                        case DeviceConnectType.NetworkTcpIp:
                            break;
                    }
                }
                ResultData.ResultCode = ResultStatus.Succeed;
                ResultData.ResultMsg = $"{this.Name} -> 初始化成功！";
            }
            catch (Exception ep)
            {
                ResultData.ResultCode = ResultStatus.Exception;
                ResultData.ResultException = ep;
                ResultData.ResultMsg = $"{this.Name} -> 初始化异常：" + ep.Message;
            }
            return ResultData;
        }

        /// <summary>
        /// 判断设备配置是否存在
        /// </summary>
        /// <param name="argDeviceName">设备配置名称</param>
        /// <returns></returns>
        public bool IsExistPara(string argDeviceName)
        {
            if (DeviceParas == null) return false;
            return DeviceParas.Exists(D => D.DeviceName == argDeviceName);
        }

        /// <summary>
        /// 判断设备配置是否存在
        /// </summary>
        /// <param name="argDevice">设备配置对象</param>
        /// <returns></returns>
        public bool IsExistPara(IDevicePara argDevice)
        {
            if (DeviceParas == null || argDevice == null) return false;
            return DeviceParas.Exists(D => D.DeviceName == argDevice.DeviceName);
        }


        /// <summary>
        /// 新增设备配置
        /// </summary>
        /// <param name="argDevicePara">设备配置对象</param>
        public void InsertDevicePara(IDevicePara argDevicePara)
        {
            if (argDevicePara == null || this.IsExistPara(argDevicePara)) return;

            DeviceType deviceType = argDevicePara.DeviceType.ToEnum<DeviceType>();
            if (deviceType == DeviceType.None) return;

            if (DeviceParas == null) { DeviceParas = new List<IDevicePara>(); }
            this.DeviceParas.Add(argDevicePara);
            IDevice<IDevicePara>? DeviceItem = null;
            switch (deviceType)
            {
                case DeviceType.Customer:
                    DeviceItem = new DeviceSerialAscii<IDevicePara>(argDevicePara);
                    break;
                case DeviceType.Electrical:
                case DeviceType.SensorSign:
                    DeviceItem = new DeviceSerialModbus<IDevicePara>(argDevicePara);
                    break;
            }
            if (DeviceItem == null) return;
            this.Manager?.InsertDevice(DeviceItem);
        }
        /// <summary>
        /// 更新设备配置
        /// </summary>
        /// <param name="argDevicePara">设备配置对象</param>
        public void UpdateDevicePara(IDevicePara argDevicePara)
        {
            if (DeviceParas == null || argDevicePara == null) return;
            switch (argDevicePara.ConnectType)
            {
                case DeviceConnectType.SerialPort:
                    UpdateDevicePara((IDeviceParaSerial)argDevicePara);
                    break;
                case DeviceConnectType.NetworkTcpIp:

                    break;
            }
        }

        /// <summary>
        /// 更新设备配置
        /// </summary>
        /// <param name="argDevicePara"></param>
        public void UpdateDevicePara(IDeviceParaSerial argDevicePara)
        {
            if (DeviceParas == null || argDevicePara == null) return;
            IDeviceParaSerial? devicePara = (IDeviceParaSerial?)this.GetDevicePara(argDevicePara.DeviceName);
            if (devicePara == null) return;

            devicePara.ModuleType = argDevicePara.ModuleType;
            devicePara.PortName = argDevicePara.PortName;
            devicePara.BaudRate = argDevicePara.BaudRate;
            devicePara.DataBits = argDevicePara.DataBits;
            devicePara.StopBits = argDevicePara.StopBits;
            devicePara.ParityBits = argDevicePara.ParityBits;
            devicePara.AutoMode = argDevicePara.AutoMode;
            //打开设备
            this.Manager?.OpenDevice(devicePara.DeviceName);
        }

        /// <summary>
        /// 删除设备配置
        /// </summary>
        /// <param name="argDeviceName">设备配置名称</param>
        public void DeleteDevicePara(string argDeviceName)
        {
            if (DeviceParas == null || string.IsNullOrWhiteSpace(argDeviceName)) { return; }
            IDevicePara? DevicePara = GetDevicePara(argDeviceName);
            if (DevicePara == null) return;
            DeleteDevicePara(DevicePara);
        }

        /// <summary>
        /// 删除配置设备
        /// </summary>
        /// <param name="argDevicePara">设备配置对象</param>
        public void DeleteDevicePara(IDevicePara argDevicePara)
        {
            if (DeviceParas == null || argDevicePara == null) { return; }
            DeviceParas.Remove(argDevicePara);
        }

        /// <summary>
        /// 保存所有设备参数
        /// </summary>
        public ResultModel<ReturnData> SaveDeviceParaAll()
        {
            ResultModel<ReturnData> ResultData = new ResultModel<ReturnData>() { ResultCode = ResultStatus.Failure, Data = new ReturnData() };
            try
            {
                if (this.DeviceParas == null || this.DeviceParas.Count <= 0) return ResultData;
                foreach (IDevicePara item in DeviceParas)
                {
                    ReturnDataRow RDataRow = new ReturnDataRow()
                    {
                        DataKey = item.DeviceName,
                        DataCaption = item.DeviceCaption,
                        DataType = item.DeviceType,
                        DataConnect = item.ConnectType.ToStringName()
                    };
                    RDataRow.DataItem.Add(new ReturnDataItem("ModuleType", item.ModuleType.ToStringName()));
                    if (item is IDeviceParaSerial paraSerial)
                    {
                        RDataRow.DataItem.Add(new ReturnDataItem("PortName", paraSerial.PortName));
                        RDataRow.DataItem.Add(new ReturnDataItem("BaudRate", paraSerial.BaudRate.ToString()));
                        RDataRow.DataItem.Add(new ReturnDataItem("DataBits", paraSerial.DataBits.ToString()));
                        RDataRow.DataItem.Add(new ReturnDataItem("StopBits", paraSerial.StopBits.ToStringName()));
                        RDataRow.DataItem.Add(new ReturnDataItem("ParityBits", paraSerial.ParityBits.ToStringName()));
                        RDataRow.DataItem.Add(new ReturnDataItem("AutoMode", paraSerial.AutoMode.ToString()));
                    }
                    ResultData.Data.DataRow.Add(RDataRow);
                }
                ResultData.ResultCode = ResultStatus.Succeed;
            }
            catch (Exception ep)
            {
                ResultData.ResultCode = ResultStatus.Exception;
                ResultData.ResultMsg = "[设备参数管理][保存所有设备参数]->异常：" + ep.Message;
            }
            return ResultData;
        }

        /// <summary>
        /// 打开所有设备
        /// </summary>
        /// <returns></returns>
        public void OpenDeviceAll()
        {
            this.Manager?.OpenDeviceAll();
        }

        /// <summary>
        /// 清除所有设备
        /// </summary>
        public void ClearDeviceAll()
        {
            if (DeviceParas != null && DeviceParas.Count > 0) { DeviceParas.Clear(); }
            this.Manager?.ClearDeviceAll();
        }


        /// <summary>
        /// 获取设备配置对象
        /// 根据设备配置索引
        /// </summary>
        /// <param name="argIndex"></param>
        /// <returns></returns>
        public IDevicePara? GetDevicePara(int argIndex)
        {
            if (DeviceParas == null) { return null; }
            return (argIndex >= 0 && argIndex < Count) ? DeviceParas[argIndex] : null;
        }

        /// <summary>
        /// 获取设备配置对象
        /// 根据设备配置名称,返回符合条件的第一个设备配置
        /// </summary>
        /// <param name="argDeviceParaName">设备配置名称</param>
        /// <returns></returns>
        public IDevicePara? GetDevicePara(string argDeviceParaName)
        {
            if (DeviceParas == null || string.IsNullOrWhiteSpace(argDeviceParaName)) { return null; }
            return DeviceParas.Where(v => v.DeviceName == argDeviceParaName).FirstOrDefault();
        }

        /// <summary>
        /// 获取设备配置对象
        /// 根据设备配置类型,返回符合条件的第一个设备配置
        /// </summary>
        /// <param name="argDeviceType">设备类型</param>
        /// <returns></returns>
        public IDevicePara? GetDevicePara(DeviceType argDeviceType)
        {
            if (DeviceParas == null) { return null; }
            return DeviceParas.Where(v => v.DeviceType == argDeviceType.ToStringName()).FirstOrDefault();
        }
    }
}
